﻿using System;
using System.Diagnostics;
using System.IO;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using Microsoft.SharePoint;
using System.Xml;

namespace EnhancedSolutions.Admin.BramNuyts.EnhancedSolutions
{
    public partial class DisposeCheckSolutions : LayoutsPageBase
    {
        private ProcessStartInfo startInfo;
        private List<string> extractDirectories;
        private const string resultPage = "DisposeCheckResult.aspx";
        private string arguments;

        protected void Page_Load(object sender, EventArgs e)
        {
            this.extractDirectories = new List<string>();
        }

        protected void Btn_Ok_Click(object sender, EventArgs e)
        {
            using (SPLongOperation operation = new SPLongOperation(this.Page))
            {
                operation.LeadingHTML = "Please wait for the disposechecker.";
                operation.TrailingHTML = "The solutions are being checked for undisposed objects.";
                operation.Begin();
                ExtractedSolutionList solList = new ExtractedSolutionList();
                foreach (ListItem item in ((SolutionsCheckBoxList)DisposeCheckSolutionsList).Items)
                {
                    if (item.Selected)
                    {
                        ExtractedSolution oSolution = new ExtractedSolution(item.Value);
                        oSolution.Extract();
                        solList.Add(oSolution);
                    }
                }

                try
                {
                    DisposeCheck(solList);
                }
                catch (Exception ex)
                {
                    throw new SPException("An error occured while disposechecking the assembly", ex);
                }
                solList.RemoveAll();
                operation.End(resultPage);
            }
        }

        private void DisposeCheck(ExtractedSolutionList solList)
        {
            string DisposePath = String.Format(@"{0}\{1}", SPUtility.GetGenericSetupPath("BIN"), Global.Default.DisposeCheckSolutions_ExeName);
            string extractfolder;
            DisposeResultList resultList = new DisposeResultList();

            foreach (ExtractedSolution solution in solList)
            {
                extractfolder = UnCab(solution);
                foreach (string filePath in Directory.GetFiles(extractfolder, "*.dll", SearchOption.AllDirectories))
                {
                    arguments = String.Format("{0} {1}", filePath, "-xml");
                    startInfo = new ProcessStartInfo(DisposePath, arguments);
                    startInfo.UseShellExecute = false;
                    startInfo.CreateNoWindow = true;
                    startInfo.RedirectStandardOutput = true;

                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        using (Process process = Process.Start(startInfo))
                        {
                            using (StreamReader reader = process.StandardOutput)
                            {
                                string message = reader.ReadToEnd();
                                XmlDocument xmlDoc = new XmlDocument();
                                xmlDoc.LoadXml(message);
                                DisposeResult result = new DisposeResult();
                                result.Message = xmlDoc;
                                resultList.Add(result);
                            }
                            process.WaitForExit();
                        }
                    });
                }
            }

            Session["DisposeResult"] = resultList;

            foreach (string dir in extractDirectories)
            {
                try
                {
                    DirectoryInfo info = new DirectoryInfo(dir);
                    info.Delete(true);
                }
                catch (Exception)
                {
                    throw new InvalidOperationException("Failed to delete the extraction folders.");
                }
            }
            
        }

        private string UnCab(ExtractedSolution solution)
        {
            string destPath = Helper.GetTemporaryPath();
            if (!Directory.Exists(destPath))
            {
                Directory.CreateDirectory(destPath);
                extractDirectories.Add(destPath);
            }
            arguments = String.Format(@"{0} -F:*.dll {1}", solution.Targetpath, destPath);
            startInfo = new ProcessStartInfo("expand", arguments);
            startInfo.UseShellExecute = false;
            startInfo.CreateNoWindow = true;

            using (Process process = Process.Start(startInfo))
            {
                process.WaitForExit();
            }

            return destPath;
        }
    }
}
